//
//  UIImage.swift
//  vr_web
//
//  Created by 李旭峰 on 2020/7/13.
//

import UIKit

enum UIImageSourceType: Int {
    case png = 1
    case jpg = 2
    case jpeg = 3
    case gif = 4
}

extension UIImage {
    func byAppendingAlpha(alpha: CGFloat) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        guard let cgImage = self.cgImage, let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        context.scaleBy(x: 1, y: -1)
        context.translateBy(x: 0, y: -self.size.height)
        context.setBlendMode(CGBlendMode.multiply)
        context.setAlpha(alpha)
        context.draw(cgImage, in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    func withTintColor(_ tintColor: UIColor, blendMode: CGBlendMode) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, 0)
        tintColor.setFill()
        let bounds = CGRect(origin: CGPoint.zero, size: self.size)
        UIRectFill(bounds)
        self.draw(in: bounds, blendMode: blendMode, alpha: 1.0)
        if blendMode != CGBlendMode.destinationIn {
            self.draw(in: bounds, blendMode: CGBlendMode.destinationIn, alpha: 1.0)
        }
        let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return tintedImage
    }
}

extension UIImage {
    
    /**
     *  将图片压缩到固定大小（可能存在稍许差距）
     *  param: image 待压缩的image
     *  param: maxM  压缩后不大于于指定大小,单位是MB
     */
    public class func compressImage(image: UIImage, maxMb: CGFloat) -> UIImage? {
        
        guard let size: size_t = image.cgImage?.bitsPerPixel else {
            return image
        }
        
        let maxLength: Int = Int(maxMb * 1024 * 1024) / size
        
        return self.compressImage(image: image, maxLength: maxLength)
    }
    
    /**
     *  将图片压缩到固定大小（可能存在稍许差距）
     *  param: image 待压缩的image
     *  param: maxM  压缩后不大于于指定大小,单位是KB
     */
    public class func compressImage(image: UIImage, maxKb: CGFloat) -> UIImage? {
        
        guard let size: size_t = image.cgImage?.bitsPerPixel else {
            return image
        }
        
        let maxLength: Int = Int(maxKb * 1024) / size
        
        return self.compressImage(image: image, maxLength: maxLength)
    }
    
    /// 压缩图片(这里的图片压缩没有计算bitsPerPixel，因为压缩前后都不计算的话就抵消了)
    /// let size: size_t = (image.cgImage?.bitsPerPixel)!
    public class func compressImage(image: UIImage,  maxLength: Int) -> UIImage? {
        
        // 设置初始的压缩比例
        var compression: CGFloat = 1
        
        // 获取初始图片的data
        guard var imageData: Data = image.jpegData(compressionQuality: compression) else {
            return nil
        }
        
        // 图片大小适合，直接返回
        if imageData.count < maxLength {
            return image
        }
        
        // 首先进行质量压缩，利用二分法找到压缩后的大小在给定的maxLength的0.9到1倍之间的data
        // 注：当图片质量低于一定程度时，继续压缩没有效果。也就是说，compression继续减小，data 也不再继续减小。所以增加了循环的次数，当6次压缩后都不能达到效果，那么结束质量压缩
        var max: CGFloat = 1    // 最大压缩比例
        var min: CGFloat = 0    // 最小压缩比例
        for _ in 0..<6 {
            
            compression = (max + min) / 2
            
            guard let tempImageData: Data = image.jpegData(compressionQuality: compression) else {
                return nil
            }
            imageData = tempImageData
            
            if (tempImageData.count < Int(CGFloat(maxLength) * 0.9)) {
                
                min = compression;
                
            } else if (tempImageData.count > maxLength) {
                
                max = compression;
                
            } else {
                break;
            }
        }
        
        if imageData.count < maxLength {
            
            // 说明质量压缩后达到了想要的图片大小，那么直接返回新图片
            return UIImage(data: imageData)
        }
        
        // 当质量压缩完成不了要求时，再进行尺寸的压缩
        guard var resultImage: UIImage = UIImage(data: imageData) else {
            return UIImage(data: imageData)
        }
        
        // Compress by size
        var lastDataLength: Int = 0
        while imageData.count > maxLength && imageData.count != lastDataLength {
            
            lastDataLength = imageData.count
            
            // 获取压缩比例
            let ratio: CGFloat = CGFloat(maxLength) / CGFloat(imageData.count)
            
            let newImageW: CGFloat = resultImage.size.width * CGFloat(sqrtf(Float(ratio)))
            let newImageH: CGFloat = resultImage.size.height * CGFloat(sqrtf(Float(ratio)))
            let size: CGSize = CGSize(width: newImageW, height: newImageH)
            
            UIGraphicsBeginImageContext(size);
            resultImage.draw(in: CGRect(x: 0, y: 0, width: newImageW, height: newImageH))
            resultImage = UIGraphicsGetImageFromCurrentImageContext() ?? resultImage
            UIGraphicsEndImageContext();
        }
        
        return resultImage
        
    }
    
    // MARK: 颜色转化成图片
    convenience init(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
        color.setFill()
        UIRectFill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage!)!)
    }
    
    /// 给定一个颜色获取指定颜色的图片，并且有上下的横线
    class func getImage(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage? {
        
        let lineHeight: CGFloat = 0.5
        
        // 获取横线图片
        let lineImage: UIImage = UIImage(color: UIColor.init(hexStr: "0xE0E0E0"), size: CGSize(width: size.width, height: lineHeight))
        
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
        
        color.setFill()
        UIRectFill(rect)
        
        lineImage.draw(in: CGRect(x: 0, y: 0, width: lineImage.size.width, height: lineHeight))
        lineImage.draw(in: CGRect(x: 0, y: size.height - lineHeight, width: lineImage.size.width, height: lineHeight))
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    /// 给定一个颜色获取指定颜色的图片，并且有上下的横线
    class func getImage(imgColor: UIColor,lineColor:UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage? {
        
        let lineHeight: CGFloat = 0.5
        
        // 获取横线图片
        let lineImage: UIImage = UIImage(color: lineColor, size: CGSize(width: size.width, height: lineHeight))
        
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
        
        imgColor.setFill()
        UIRectFill(rect)
        
        lineImage.draw(in: CGRect(x: 0, y: 0, width: lineImage.size.width, height: lineHeight))
        lineImage.draw(in: CGRect(x: 0, y: size.height - lineHeight, width: lineImage.size.width, height: lineHeight))
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    // MARK: 比例化缩放图片
    func scaleImage(scale: CGSize) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(scale,false,UIScreen.main.scale);
        self.draw(in: CGRect(x: 0, y: 0, width: scale.width, height: scale.height))
        let reSizeImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!;
        UIGraphicsEndImageContext();
        return reSizeImage;
    }
    
    // MARK: 根据名字取图片
    func getImgView(_ ImgName: NSString)->UIImage{
        var image:UIImage = UIImage(named: ImgName as String)!
        image = image.withRenderingMode(UIImage.RenderingMode.alwaysOriginal);
        return image;
    }
    
    /// 给指定的图片打上水印
//    public func getWaterMarkImage(headerView: UIView?) -> UIImage?{
//
//        let headerImage = headerView?.getCurrentViewImage()
//
//        return self.getWaterMarkImage(headerImage: headerImage)
//    }
    
    /// 给指定的图片打上水印
//    public func getWaterMarkImage(headerImage: UIImage?, backgroundImage: UIImage? = nil) -> UIImage?{
//
//        let headerImage = headerImage
//
//        let oryginImage = self
//
//        let waterMark: WaterMarkView = WaterMarkView(originImage: oryginImage, headerImage: headerImage, backgroundImage: backgroundImage)
//
//        return waterMark.getCurrentViewImage()
//    }
    
    func getGradientImage(gradientColors: [UIColor], size: CGSize) -> UIImage {
        
        UIGraphicsBeginImageContextWithOptions(size, true, 1)
        
        //获取绘图上下文
        guard let context = UIGraphicsGetCurrentContext() else {
            return UIImage()
        }
        
        //使用rgb颜色空间
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        //颜色数组（这里使用三组颜色作为渐变）fc6820
        let compoents:[CGFloat] = [0xfc/255, 0x68/255, 0x20/255, 1,
                                   0xfe/255, 0xd3/255, 0x2f/255, 1,
                                   0xb1/255, 0xfc/255, 0x33/255, 1]
        //没组颜色所在位置（范围0~1)
        let locations:[CGFloat] = [0,1]
        //生成渐变色（count参数表示渐变个数）
        let gradient = CGGradient(colorSpace: colorSpace, colorComponents: compoents,
                                  locations: locations, count: locations.count)!
        
        //渐变开始位置
        let start = CGPoint(x: 0, y: 0)
        //渐变结束位置
        let end = CGPoint(x: size.width, y: size.height)
        //绘制渐变
        context.drawLinearGradient(gradient, start: start, end: end,
                                   options: .drawsBeforeStartLocation)
        
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
        UIGraphicsEndImageContext()
        
        return image
    }
    
    /**
     * 获取帖子详情里面的图片的默认图片
     */
    class func getPostDetailPlaceholderImage(backgroundColor: UIColor = UIColor.init(hexStr: "0xEEEEEE"), centerImage: UIImage? = UIImage(named: "icon_picture_place_holder"), size: CGSize) -> UIImage? {
        
        UIGraphicsBeginImageContextWithOptions(size, true, 1)
        
        //获取需要绘制的图片
        guard let renderImage = centerImage else { return nil }
        
        UIImage(color: backgroundColor).draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        
        // 将中间的图片渲染在背景的中间
        let imageW: CGFloat = size.width * 0.25
        let imageH: CGFloat = renderImage.size.height * imageW / renderImage.size.width
        let imageX: CGFloat = (size.width - imageW) / 2
        let imageY: CGFloat = (size.height - imageH) / 2
        renderImage.draw(in: CGRect(x: imageX, y: imageY, width: imageW, height: imageH))
        
        let image: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    /// 获取网络图片尺寸
    /// - Parameter url: 网络图片链接
    /// - Returns: 图片尺寸size
    class func getImageSize(_ url: String?) -> CGSize {
        
        guard let urlStr = url else {
            
            return CGSize.zero
        }
        
        guard let tempUrl = URL(string: urlStr) else {
            return CGSize.zero
        }
        
        let imageSourceRef = CGImageSourceCreateWithURL(tempUrl as CFURL, nil)
        
        var width: CGFloat = 0
        
        var height: CGFloat = 0
        
        if let imageSRef = imageSourceRef {
            
            let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSRef, 0, nil)
            
            if let imageP = imageProperties {
                
                let imageDict = imageP as Dictionary
                
                width = imageDict[kCGImagePropertyPixelWidth] as! CGFloat
                
                height = imageDict[kCGImagePropertyPixelHeight] as! CGFloat
                
            }
        }
        
        return CGSize(width: width, height: height)
    }
    
    /**
     *  给定一张图片,进行左右拉伸,中间保持原图不变,仅仅适用于带尖括号的图片
     *  param: sImage 被拉伸的图片
     *  param: margin 左右边距
     *  param: destImageSize 拉伸后图片的大小
     */
    func stretchImage(sImage: UIImage?, margin: CGFloat, destImageSize: CGSize) -> UIImage? {
        
        guard let sourceImage = sImage else {
            return nil
        }
        
        //原始图片,左右拉伸的距离可以是20
        let sourceWidth = sourceImage.size.width
        let sourceHeight = sourceImage.size.height
        let stretchMargin = margin
        
        //最终大小
        let destWidth = destImageSize.width
        let destHeight = destImageSize.height
        
        //第一次对图片进行拉伸
        let image: UIImage = sourceImage.stretchableImage(withLeftCapWidth: Int(stretchMargin), topCapHeight: Int(sourceHeight * 0.5))
        
        let imageV: UIImageView = UIImageView(image: image)
        
        //第一次拉伸宽度=最终宽度/2+原图宽度/2
        let tempWidth: CGFloat = destWidth * 0.5 + sourceWidth * 0.5
        
        imageV.frame = CGRect(x: 0, y: 0, width: tempWidth, height: destHeight)
        
        //将临时的图片进行绘制,将上面的临时图片被绘制出来
        UIGraphicsBeginImageContextWithOptions(CGSize(width: tempWidth, height: destHeight), false, UIScreen.main.scale)
        
        imageV.image?.draw(in: CGRect(x: 0, y: 0, width: tempWidth, height: destHeight))
        let imageTemp: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        
        //将绘制出来的临时图片再次进行拉伸
        imageV.frame = CGRect(x: 0, y: 0, width: destWidth, height: destHeight)
        imageV.image = imageTemp.stretchableImage(withLeftCapWidth: Int(tempWidth - stretchMargin), topCapHeight: Int(sourceHeight * 0.5))
        return imageV.image
    }
    
    /**
     *  给定一张图片,进行左右拉伸,仅仅适用于带尖括号的图片
     *  param: sImage 被拉伸的图片
     *  param: margin 距离左边的边距
     *  param: destImageSize 拉伸后图片的大小
     */
    func stretchImageFixedLeft(marginLeft: CGFloat, destImageSize: CGSize) -> UIImage {
        
        let sourceImage = self
        
        //原始图片,左右拉伸的距离可以是20
        let sourceHeight = sourceImage.size.height
        let stretchMargin = marginLeft
        
        //对图片进行拉伸
        let image: UIImage = sourceImage.stretchableImage(withLeftCapWidth: Int(stretchMargin), topCapHeight: Int(sourceHeight * 0.5))
        
        return image
    }
    
    public func fixOrientation(orientation: Orientation) -> UIImage? {
        
        guard let aCGImage = self.cgImage else {
            return nil
        }
        
        let pixelsWidth: Int
        let pixelsHeight: Int
        
        pixelsWidth = aCGImage.width
        pixelsHeight = aCGImage.height
        
        guard let colorSpace = aCGImage.colorSpace,
            let context = CGContext(data: nil, width: pixelsWidth, height: pixelsHeight, bitsPerComponent: aCGImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: aCGImage.bitmapInfo.rawValue) else {
                return nil
        }
        
        context.draw(aCGImage, in: CGRect(x: 0, y: 0, width: pixelsWidth, height: pixelsHeight))
        guard let newCGImage = context.makeImage() else {
            return nil
        }
        let newImage = UIImage(cgImage: newCGImage, scale: scale, orientation: .up)
        return newImage
    }
    
    // 获取指定颜色的空心点图片
    static func getDotImage(size: CGSize, color: UIColor) -> UIImage {
        
        UIGraphicsBeginImageContextWithOptions(size, true, 1)
        
        //获取绘图上下文
        guard let context = UIGraphicsGetCurrentContext() else {
            return UIImage()
        }
        
        let centerPoint: CGPoint = CGPoint(x: size.width / 2, y: size.height / 2)
        
        context.setFillColor(color.cgColor)
        context.addArc(center: centerPoint, radius: size.width / 2, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
        context.fillPath()
        context.setFillColor(UIColor.white.cgColor)
        context.addArc(center: centerPoint, radius: size.width / 4, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
        context.fillPath()
        
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
        UIGraphicsEndImageContext()
        
        return image
    }
}
extension UIImage {
    func toData() -> Data? {
        return self.jpegData(compressionQuality: 1.0)
    }
}
extension UIImage {
    static func image(withView view:UIView) -> UIImage? {
        UIGraphicsBeginImageContext(view.bounds.size);
        guard let ctx = UIGraphicsGetCurrentContext() else { return nil }
        view.layer.render(in: ctx)
        let tImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return tImage
    }
}

